#include "lsp_server.h"

#include <boost/test/unit_test.hpp>

#include <sstream>


BOOST_AUTO_TEST_SUITE(lsp_server_test_suite);

BOOST_AUTO_TEST_CASE(test_case1)
{
	std::istringstream input{
		"Content-Length: 465\r\n\r\n{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"processId\":20943,\"rootPath\":\"/Users/dmakarov/work/try/p4ls/\",\"rootUri\":\"file:///Users/dmakarov/work/try/p4ls/\",\"capabilities\":{\"workspace\":{\"applyEdit\":true,\"executeCommand\":{\"dynamicRegistration\":true}},\"textDocument\":{\"synchronization\":{\"willSave\":true,\"didSave\":true},\"symbol\":{\"symbolKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}}}},\"initializationOptions\":null},\"id\":1}"
	};
	std::ostringstream output;
	LSP_server lsp(input, output);
	BOOST_REQUIRE_EQUAL(lsp.run(), 0);
}

BOOST_AUTO_TEST_CASE(test_case2)
{
	std::istringstream input{
		"Content-Length: 125\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"initialize\",\"params\":{\"processId\":123,\"rootPath\":\"clangd\",\"capabilities\":{},\"trace\":\"off\"}}"
		"Content-Length: 44\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"shutdown\"}"
	};
	std::ostringstream output;
	LSP_server lsp(input, output);
	BOOST_REQUIRE_EQUAL(lsp.run(), 0);
}

BOOST_AUTO_TEST_CASE(test_case3)
{
	std::istringstream input{
		"Content-Length: 757\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"method\":\"initialize\",\"params\":{\"processId\":46350,\"rootPath\":\"/Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/\",\"rootUri\":\"file:///Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/\",\"capabilities\":{\"workspace\":{\"applyEdit\":true,\"symbol\":{},\"executeCommand\":{\"dynamicRegistration\":true},\"workspaceFolders\":true},\"textDocument\":{\"synchronization\":{\"willSave\":true,\"willSaveWaitUntil\":true,\"didSave\":true},\"completion\":{\"completionItem\":{\"snippetSupport\":true}},\"hover\":{},\"signatureHelp\":{},\"references\":{},\"documentHighlight\":{},\"documentSymbol\":{},\"formatting\":{},\"rangeFormatting\":{},\"definition\":{},\"codeAction\":{},\"codeLens\":{},\"documentLink\":{},\"rename\":{}}},\"clientName\":\"Eclipse SDK\"}}"
		"Content-Length: 52\r\n\r\n{\"jsonrpc\":\"2.0\",\"method\":\"initialized\",\"params\":{}}"
		"Content-Length: 10355\r\n\r\n{\"jsonrpc\":\"2.0\",\"method\":\"textDocument/didOpen\",\"params\":{\"textDocument\":{\"uri\":\"file:///Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/main.p4\",\"languageId\":\"p4\",\"version\":1,\"text\":\"# 1 \\\"/Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/main.p4\\\"\\n# 1 \\\"\\u003cbuilt-in\\u003e\\\" 1\\n# 1 \\\"\\u003cbuilt-in\\u003e\\\" 3\\n# 341 \\\"\\u003cbuilt-in\\u003e\\\" 3\\n# 1 \\\"\\u003ccommand line\\u003e\\\" 1\\n# 1 \\\"\\u003cbuilt-in\\u003e\\\" 2\\n# 1 \\\"/Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/main.p4\\\" 2\\n\\n# 1 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/core.p4\\\" 1\\n# 23 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/core.p4\\\"\\nerror {\\n    NoError,\\n    PacketTooShort,\\n    NoMatch,\\n    StackOutOfBounds,\\n    HeaderTooShort,\\n    ParserTimeout\\n}\\n\\nextern packet_in {\\n\\n\\n\\n    void extract\\u003cT\\u003e(out T hdr);\\n\\n\\n\\n\\n    void extract\\u003cT\\u003e(out T variableSizeHeader,\\n                    in bit\\u003c32\\u003e variableFieldSizeInBits);\\n\\n\\n\\n    T lookahead\\u003cT\\u003e();\\n\\n    void advance(in bit\\u003c32\\u003e sizeInBits);\\n\\n\\n    bit\\u003c32\\u003e length();\\n}\\n\\nextern packet_out {\\n\\n\\n\\n    void emit\\u003cT\\u003e(in T hdr);\\n}\\n\\n\\n\\n\\nextern void verify(in bool check, in error toSignal);\\n\\n\\naction NoAction() {}\\n\\n\\n\\n\\nmatch_kind {\\n\\n    exact,\\n\\n    ternary,\\n\\n    lpm\\n}\\n# 3 \\\"/Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/main.p4\\\" 2\\n# 1 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\" 1\\n# 24 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\"\\nmatch_kind {\\n    range,\\n\\n    selector\\n}\\n\\n\\n@metadata @name(\\\"standard_metadata\\\")\\nstruct standard_metadata_t {\\n    bit\\u003c9\\u003e ingress_port;\\n    bit\\u003c9\\u003e egress_spec;\\n    bit\\u003c9\\u003e egress_port;\\n    bit\\u003c32\\u003e clone_spec;\\n    bit\\u003c32\\u003e instance_type;\\n    bit\\u003c1\\u003e drop;\\n    bit\\u003c16\\u003e recirculate_port;\\n    bit\\u003c32\\u003e packet_length;\\n# 50 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\"\\n    @alias(\\\"queueing_metadata.enq_timestamp\\\") bit\\u003c32\\u003e enq_timestamp;\\n    @alias(\\\"queueing_metadata.enq_qdepth\\\") bit\\u003c19\\u003e enq_qdepth;\\n    @alias(\\\"queueing_metadata.deq_timedelta\\\") bit\\u003c32\\u003e deq_timedelta;\\n    @alias(\\\"queueing_metadata.deq_qdepth\\\") bit\\u003c19\\u003e deq_qdepth;\\n\\n    @alias(\\\"intrinsic_metadata.ingress_global_timestamp\\\") bit\\u003c48\\u003e ingress_global_timestamp;\\n    @alias(\\\"intrinsic_metadata.egress_global_timestamp\\\") bit\\u003c48\\u003e egress_global_timestamp;\\n    @alias(\\\"intrinsic_metadata.lf_field_list\\\") bit\\u003c32\\u003e lf_field_list;\\n    @alias(\\\"intrinsic_metadata.mcast_grp\\\") bit\\u003c16\\u003e mcast_grp;\\n    @alias(\\\"intrinsic_metadata.resubmit_flag\\\") bit\\u003c32\\u003e resubmit_flag;\\n    @alias(\\\"intrinsic_metadata.egress_rid\\\") bit\\u003c16\\u003e egress_rid;\\n\\n    bit\\u003c1\\u003e checksum_error;\\n    @alias(\\\"intrinsic_metadata.recirculate_flag\\\") bit\\u003c32\\u003e recirculate_flag;\\n}\\n\\nenum CounterType {\\n    packets,\\n    bytes,\\n    packets_and_bytes\\n}\\n\\nenum MeterType {\\n    packets,\\n    bytes\\n}\\n\\nextern counter {\\n    counter(bit\\u003c32\\u003e size, CounterType type);\\n    void count(in bit\\u003c32\\u003e index);\\n}\\n\\nextern direct_counter {\\n    direct_counter(CounterType type);\\n    void count();\\n}\\n\\nextern meter {\\n    meter(bit\\u003c32\\u003e size, MeterType type);\\n    void execute_meter\\u003cT\\u003e(in bit\\u003c32\\u003e index, out T result);\\n}\\n\\nextern direct_meter\\u003cT\\u003e {\\n    direct_meter(MeterType type);\\n    void read(out T result);\\n}\\n\\nextern register\\u003cT\\u003e {\\n    register(bit\\u003c32\\u003e size);\\n    void read(out T result, in bit\\u003c32\\u003e index);\\n    void write(in bit\\u003c32\\u003e index, in T value);\\n}\\n\\n\\nextern action_profile {\\n    action_profile(bit\\u003c32\\u003e size);\\n}\\n\\n\\nextern void random\\u003cT\\u003e(out T result, in T lo, in T hi);\\n\\n\\nextern void digest\\u003cT\\u003e(in bit\\u003c32\\u003e receiver, in T data);\\n\\nenum HashAlgorithm {\\n    crc32,\\n    crc32_custom,\\n    crc16,\\n    crc16_custom,\\n    random,\\n    identity,\\n    csum16,\\n    xor16\\n}\\n\\nextern void mark_to_drop();\\nextern void hash\\u003cO, T, D, M\\u003e(out O result, in HashAlgorithm algo, in T base, in D data, in M max);\\n\\nextern action_selector {\\n    action_selector(HashAlgorithm algorithm, bit\\u003c32\\u003e size, bit\\u003c32\\u003e outputWidth);\\n}\\n\\nenum CloneType {\\n    I2E,\\n    E2E\\n}\\n\\n@deprecated(\\\"Please use verify_checksum/update_checksum instead.\\\")\\nextern Checksum16 {\\n    Checksum16();\\n    bit\\u003c16\\u003e get\\u003cD\\u003e(in D data);\\n}\\n# 156 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\"\\nextern void verify_checksum\\u003cT, O\\u003e(in bool condition, in T data, inout O checksum, HashAlgorithm algo);\\n# 168 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\"\\nextern void update_checksum\\u003cT, O\\u003e(in bool condition, in T data, inout O checksum, HashAlgorithm algo);\\n# 184 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\"\\nextern void verify_checksum_with_payload\\u003cT, O\\u003e(in bool condition, in T data, inout O checksum, HashAlgorithm algo);\\n# 197 \\\"/Users/dmakarov/work/try/p4c/build/ninja/p4include/v1model.p4\\\"\\nextern void update_checksum_with_payload\\u003cT, O\\u003e(in bool condition, in T data, inout O checksum, HashAlgorithm algo);\\n\\nextern void resubmit\\u003cT\\u003e(in T data);\\nextern void recirculate\\u003cT\\u003e(in T data);\\nextern void clone(in CloneType type, in bit\\u003c32\\u003e session);\\nextern void clone3\\u003cT\\u003e(in CloneType type, in bit\\u003c32\\u003e session, in T data);\\n\\nextern void truncate(in bit\\u003c32\\u003e length);\\n\\n\\n\\n\\n\\n\\n\\nparser Parser\\u003cH, M\\u003e(packet_in b,\\n                    out H parsedHdr,\\n                    inout M meta,\\n                    inout standard_metadata_t standard_metadata);\\n\\n\\n\\n\\n\\ncontrol VerifyChecksum\\u003cH, M\\u003e(inout H hdr,\\n                             inout M meta);\\n@pipeline\\ncontrol Ingress\\u003cH, M\\u003e(inout H hdr,\\n                      inout M meta,\\n                      inout standard_metadata_t standard_metadata);\\n@pipeline\\ncontrol Egress\\u003cH, M\\u003e(inout H hdr,\\n                     inout M meta,\\n                     inout standard_metadata_t standard_metadata);\\n\\n\\n\\n\\n\\ncontrol ComputeChecksum\\u003cH, M\\u003e(inout H hdr,\\n                              inout M meta);\\n@deparser\\ncontrol Deparser\\u003cH\\u003e(packet_out b, in H hdr);\\n\\npackage V1Switch\\u003cH, M\\u003e(Parser\\u003cH, M\\u003e p,\\n                       VerifyChecksum\\u003cH, M\\u003e vr,\\n                       Ingress\\u003cH, M\\u003e ig,\\n                       Egress\\u003cH, M\\u003e eg,\\n                       ComputeChecksum\\u003cH, M\\u003e ck,\\n                       Deparser\\u003cH\\u003e dep\\n                       );\\n# 4 \\\"/Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/main.p4\\\" 2\\n\\nconst bit\\u003c16\\u003e TYPE_IPV4 \\u003d 0x800;\\n\\n\\n\\n\\n\\ntypedef bit\\u003c9\\u003e egressSpec_t;\\ntypedef bit\\u003c48\\u003e macAddr_t;\\ntypedef bit\\u003c32\\u003e ip4Addr_t;\\n\\nheader ethernet_t {\\n    macAddr_t dstAddr;\\n    macAddr_t srcAddr;\\n    bit\\u003c16\\u003e etherType;\\n}\\n\\nheader ipv4_t {\\n    bit\\u003c4\\u003e version;\\n    bit\\u003c4\\u003e ihl;\\n    bit\\u003c8\\u003e diffserv;\\n    bit\\u003c16\\u003e totalLen;\\n    bit\\u003c16\\u003e identification;\\n    bit\\u003c3\\u003e flags;\\n    bit\\u003c13\\u003e fragOffset;\\n    bit\\u003c8\\u003e ttl;\\n    bit\\u003c8\\u003e protocol;\\n    bit\\u003c16\\u003e hdrChecksum;\\n    ip4Addr_t srcAddr;\\n    ip4Addr_t dstAddr;\\n}\\n\\nstruct metadata {\\n\\n}\\n\\nstruct headers {\\n    ethernet_t ethernet;\\n    ipv4_t ipv4;\\n}\\n\\n\\n\\n\\n\\nparser MyParser(packet_in packet,\\n                out headers hdr,\\n                inout metadata meta,\\n                inout standard_metadata_t standard_metadata) {\\n\\n    state start {\\n        transition parse_ethernet;\\n    }\\n\\n    state parse_ethernet {\\n        packet.extract(hdr.ethernet);\\n        transition select(hdr.ethernet.etherType) {\\n            TYPE_IPV4: parse_ipv4;\\n            default: accept;\\n        }\\n    }\\n\\n    state parse_ipv4 {\\n        packet.extract(hdr.ipv4);\\n        transition accept;\\n    }\\n\\n}\\n\\n\\n\\n\\n\\ncontrol MyVerifyChecksum(inout headers hdr, inout metadata meta) {\\n    apply { }\\n}\\n\\n\\n\\n\\n\\n\\ncontrol MyIngress(inout headers hdr,\\n                  inout metadata meta,\\n                  inout standard_metadata_t standard_metadata) {\\n    action drop() {\\n        mark_to_drop();\\n    }\\n\\n    action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {\\n        standard_metadata.egress_spec \\u003d port;\\n        hdr.ethernet.srcAddr \\u003d hdr.ethernet.dstAddr;\\n        hdr.ethernet.dstAddr \\u003d dstAddr;\\n        hdr.ipv4.ttl \\u003d hdr.ipv4.ttl - 1;\\n    }\\n\\n    table ipv4_lpm {\\n        key \\u003d {\\n            hdr.ipv4.dstAddr: lpm;\\n        }\\n        actions \\u003d {\\n            ipv4_forward;\\n            drop;\\n            NoAction;\\n        }\\n        size \\u003d 1024;\\n        default_action \\u003d drop();\\n    }\\n\\n    apply {\\n        if (hdr.ipv4.isValid()) {\\n            ipv4_lpm.apply();\\n        }\\n    }\\n}\\n\\n\\n\\n\\n\\ncontrol MyEgress(inout headers hdr,\\n                 inout metadata meta,\\n                 inout standard_metadata_t standard_metadata) {\\n    apply { }\\n}\\n\\n\\n\\n\\n\\ncontrol MyComputeChecksum(inout headers hdr, inout metadata meta) {\\n     apply {\\n update_checksum(\\n     hdr.ipv4.isValid(),\\n            { hdr.ipv4.version,\\n       hdr.ipv4.ihl,\\n              hdr.ipv4.diffserv,\\n              hdr.ipv4.totalLen,\\n              hdr.ipv4.identification,\\n              hdr.ipv4.flags,\\n              hdr.ipv4.fragOffset,\\n              hdr.ipv4.ttl,\\n              hdr.ipv4.protocol,\\n              hdr.ipv4.srcAddr,\\n              hdr.ipv4.dstAddr },\\n            hdr.ipv4.hdrChecksum,\\n            HashAlgorithm.csum16);\\n    }\\n}\\n\\n\\n\\n\\n\\ncontrol MyDeparser(packet_out packet, in headers hdr) {\\n    apply {\\n        packet.emit(hdr.ethernet);\\n        packet.emit(hdr.ipv4);\\n    }\\n}\\n\\n\\n\\n\\n\\nV1Switch(\\nMyParser(),\\nMyVerifyChecksum(),\\nMyIngress(),\\nMyEgress(),\\nMyComputeChecksum(),\\nMyDeparser()\\n) main;\\n\"}}}"
		"Content-Length: 185\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":\"2\",\"method\":\"textDocument/documentSymbol\",\"params\":{\"textDocument\":{\"uri\":\"file:///Users/dmakarov/work/try/wtests/runtime-EclipseApplication/p4ls-test/main.p4\"}}}"
		"Content-Length: 60\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":\"3\",\"method\":\"shutdown\",\"params\":null}"
	};
	std::ostringstream output;
	LSP_server lsp(input, output);
	BOOST_REQUIRE_EQUAL(lsp.run(), 0);
}

BOOST_AUTO_TEST_SUITE_END();
